using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using BEPUphysics;
using Asplode.Renderer;
using BEPUphysics.Entities;
using Asplode.Physics;
using Asplode.GameWorld;
using Asplode.InputHandler;
using System.IO;

namespace Asplode
{
    public class Game : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        public AsplodeMap Map;
        private AsplodeRenderer Renderer;

        public EventDispatcher EventDispatcher;
        public InputManager InputManager;

        public float camRotation;

        float aspectRatio;

        public Console console;
        public FPSCounter fpsCounter;

        public Space Physics;

        GameWorld.GameWorld GameWorld;

        public Game()
        {
            graphics = new GraphicsDeviceManager(this);
            EventDispatcher = EventDispatcher.Instance;
            InputManager = new InputManager();

            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            aspectRatio = graphics.GraphicsDevice.Viewport.AspectRatio;
            graphics.GraphicsDevice.RenderState.DepthBufferEnable = true;
            int width = GraphicsDevice.Viewport.Width;
            int depth = GraphicsDevice.Viewport.Height;

            this.IsMouseVisible = true;

            Map = new AsplodeMap(graphics.GraphicsDevice);
            Map.Camera.UpdateTopDownMode(new Vector3(0, 50, 5));
            Map.Camera.GraphicsDevice = GraphicsDevice;

            Map.Width = width;
            Map.Depth = depth;

            Renderer = new AsplodeRenderer(this);
            var AsplodeRendererEventHandler = new AsplodeRendererEventHandler(Renderer);

            GameWorld = new GameWorld.GameWorld(EventDispatcher, Map, InputManager);
            var GameWorldEventHandler = new GameWorldEventHandler(GameWorld);

            Physics = new Space();
            Physics.simulationSettings.motionUpdate.gravity = new Vector3(0, -9.81f, 0);
            Physics.simulationSettings.collisionResponse.iterations = 2;
            Physics.simulationSettings.timeStep.useInternalTimeStepping = true;
            var PhysicsEventHandler = new PhysicsEventHandler(Physics);

            AsplodeRendererEventHandler.subscribe(EventDispatcher);
            GameWorldEventHandler.subscribe(EventDispatcher);
            PhysicsEventHandler.subscribe(EventDispatcher);

            //Physics.simulationSettings.collisionDetection.collisionDetectionType = CollisionDetectionType.discreteMPRGJK;
            

            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            Map.LoadContent(Content);

            console = new Console(Content, spriteBatch);

            console.Print("press 1 to select the box gun");
            console.Print("press 2 to select the mortar");
            console.Print("");
            console.Print("click to fire");

            fpsCounter = new FPSCounter(Content, spriteBatch);
            fpsCounter.position = new Vector2(20, GraphicsDevice.Viewport.Height - 40);

            GameWorld.Initialize();
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.I))
            {
                GameWorld.ClearWorld();
                GameWorld.Initialize();
            }
            Physics.update(gameTime);
            GameWorld.Update(gameTime);

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            fpsCounter.Print("" + (int)(1000 / gameTime.ElapsedGameTime.TotalMilliseconds));

            //Map.Draw(GraphicsDevice,camRotation);

            GraphicsDevice.RenderState.DepthBufferEnable = true;
            // Draw everything in the Components collection.
            // base.Draw(gameTime);
            GraphicsDevice.RenderState.DepthBufferEnable = true;
            Renderer.Draw();

            spriteBatch.Begin();
            console.Draw();
            fpsCounter.Update(gameTime);
            fpsCounter.Draw();
            spriteBatch.End();

            GraphicsDevice.RenderState.AlphaBlendEnable = true;
            GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
            GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;

            GraphicsDevice.RenderState.DepthBufferEnable = true;
        }
    }
}